//! 数据客户端模块
//! 
//! 提供数据获取和连接功能

use anyhow::Result;
use chrono::{DateTime, Utc, Datelike};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

use crate::objects::{bar::RawBar, enums::Freq};

/// 数据客户端配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataClientConfig {
    /// 数据源类型
    pub source: String,
    /// 连接配置
    pub connection: HashMap<String, String>,
    /// 缓存配置
    pub cache: HashMap<String, String>,
}

/// 数据客户端
pub struct DataClient {
    /// 配置
    pub config: DataClientConfig,
    /// 缓存
    pub cache: HashMap<String, Vec<RawBar>>,
}

impl DataClient {
    /// 创建新的数据客户端
    pub fn new(config: DataClientConfig) -> Self {
        Self {
            config,
            cache: HashMap::new(),
        }
    }

    /// 获取K线数据
    pub async fn get_bars(
        &mut self,
        symbol: &str,
        freq: &Freq,
        start_dt: Option<DateTime<Utc>>,
        end_dt: Option<DateTime<Utc>>,
    ) -> Result<Vec<RawBar>> {
        // 构建缓存键
        let cache_key = format!("{}_{}_{}_{}_{}", 
            symbol, 
            freq, 
            start_dt.map(|dt| dt.timestamp()).unwrap_or(0),
            end_dt.map(|dt| dt.timestamp()).unwrap_or(0),
            self.config.source
        );

        // 检查缓存
        if let Some(cached_bars) = self.cache.get(&cache_key) {
            return Ok(cached_bars.clone());
        }

        // 从数据源获取数据
        let bars = match self.config.source.as_str() {
            "mock" => self.get_mock_bars(symbol, freq, start_dt, end_dt).await?,
            "csv" => self.get_csv_bars(symbol, freq, start_dt, end_dt).await?,
            "database" => self.get_database_bars(symbol, freq, start_dt, end_dt).await?,
            _ => return Err(anyhow::anyhow!("不支持的数据源: {}", self.config.source)),
        };

        // 缓存数据
        self.cache.insert(cache_key, bars.clone());

        Ok(bars)
    }

    /// 获取模拟数据
    async fn get_mock_bars(
        &self,
        symbol: &str,
        freq: &Freq,
        start_dt: Option<DateTime<Utc>>,
        end_dt: Option<DateTime<Utc>>,
    ) -> Result<Vec<RawBar>> {
        let start = start_dt.unwrap_or_else(|| Utc::now() - chrono::Duration::days(30));
        let end = end_dt.unwrap_or_else(|| Utc::now());
        
        let mut bars = Vec::new();
        let mut current_dt = start;
        let mut id = 1;

        while current_dt <= end {
            // 生成模拟价格数据
            let base_price = 100.0 + (id as f64 * 0.1);
            let open = base_price + (rand::random::<f64>() - 0.5) * 2.0;
            let close = open + (rand::random::<f64>() - 0.5) * 2.0;
            let high = open.max(close) + rand::random::<f64>() * 1.0;
            let low = open.min(close) - rand::random::<f64>() * 1.0;
            let vol = 1000000.0 + rand::random::<f64>() * 500000.0;
            let amount = vol * (open + close) / 2.0;

            let bar = RawBar::new(
                symbol.to_string(),
                id,
                current_dt,
                freq.clone(),
                open,
                close,
                high,
                low,
                vol,
                amount,
            );

            bars.push(bar);

            // 更新时间
            current_dt = match freq {
                Freq::Min1 => current_dt + chrono::Duration::minutes(1),
                Freq::Min5 => current_dt + chrono::Duration::minutes(5),
                Freq::Min15 => current_dt + chrono::Duration::minutes(15),
                Freq::Min30 => current_dt + chrono::Duration::minutes(30),
                Freq::Min60 => current_dt + chrono::Duration::minutes(60),
                Freq::Day => current_dt + chrono::Duration::days(1),
                Freq::Week => current_dt + chrono::Duration::weeks(1),
                Freq::Month => {
                    // 简单的月份计算
                    let mut new_month = current_dt.month() + 1;
                    let mut new_year = current_dt.year();
                    if new_month > 12 {
                        new_month = 1;
                        new_year += 1;
                    }
                    current_dt.with_year(new_year).unwrap().with_month(new_month).unwrap()
                }
                Freq::Quarter => current_dt + chrono::Duration::days(90),
                Freq::Year => current_dt + chrono::Duration::days(365),
            };

            id += 1;
        }

        Ok(bars)
    }

    /// 从CSV文件获取数据
    async fn get_csv_bars(
        &self,
        _symbol: &str,
        _freq: &Freq,
        _start_dt: Option<DateTime<Utc>>,
        _end_dt: Option<DateTime<Utc>>,
    ) -> Result<Vec<RawBar>> {
        // TODO: 实现CSV数据读取
        Err(anyhow::anyhow!("CSV数据源暂未实现"))
    }

    /// 从数据库获取数据
    async fn get_database_bars(
        &self,
        _symbol: &str,
        _freq: &Freq,
        _start_dt: Option<DateTime<Utc>>,
        _end_dt: Option<DateTime<Utc>>,
    ) -> Result<Vec<RawBar>> {
        // TODO: 实现数据库数据读取
        Err(anyhow::anyhow!("数据库数据源暂未实现"))
    }

    /// 清除缓存
    pub fn clear_cache(&mut self) {
        self.cache.clear();
    }

    /// 获取缓存大小
    pub fn cache_size(&self) -> usize {
        self.cache.len()
    }
}

impl std::fmt::Display for DataClient {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "DataClient(source={}, cache_size={})",
            self.config.source,
            self.cache_size()
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::objects::enums::Freq;

    #[tokio::test]
    async fn test_data_client() {
        let config = DataClientConfig {
            source: "mock".to_string(),
            connection: HashMap::new(),
            cache: HashMap::new(),
        };

        let mut client = DataClient::new(config);
        
        let bars = client.get_bars("000001.SZ", &Freq::Day, None, None).await.unwrap();
        
        assert!(!bars.is_empty());
        assert_eq!(bars[0].symbol, "000001.SZ");
        assert_eq!(bars[0].freq, Freq::Day);
    }
} 